package com.ww.cheappliers.dynload;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 动态加载类
 * @author tengHY
 *
 */
public class DynamicLoad {
	public static final File classBase;
	static{
		try {
			classBase 
				= new File(
						DynamicLoad.class.getResource("/").toURI());
			if(!classBase.isDirectory())
				classBase.mkdirs();
		} catch (URISyntaxException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 数据写入文件
	 * @param name
	 * @param fileData
	 * @param replace
	 * @throws IOException
	 */
	public File storeJavaFile(String fullClassName, byte[] fileData
			, boolean replace) throws IOException{
		String[] pc = getClassPackageAndName(fullClassName);
		File dirBase = new File(classBase, packageName2Path(pc[0]));
		if(!dirBase.isDirectory())
			dirBase.mkdirs();
		
		File f = new File(dirBase, pc[1] + ".java");
		
		if(!replace && f.isFile())
			throw new RuntimeException("文件已存在");
		
		// save
		FileUtils.writeByteArrayToFile(f, fileData);
		return f;
	}
	
	private static String[] getClassPackageAndName(String classFullName){
		classFullName = StringUtils.trimToEmpty(classFullName);
		int lastDot = classFullName.lastIndexOf('.');
		if(lastDot < 0)
			return new String[]{"", classFullName};
		
		return new String[]{classFullName.substring(0, lastDot).trim()
				, classFullName.substring(lastDot, classFullName.length()).trim()};
	}
	
	public Class<?> loadJavaClass(String classFullName) 
			throws MalformedURLException, ClassNotFoundException{
		String[] pc = getClassPackageAndName(classFullName);
		File classDir = new File(classBase, packageName2Path(pc[0]));
		URLClassLoader ul = new URLClassLoader(new URL[]{classDir.toURI().toURL()});

		Class<?> c = ul.loadClass(classFullName) ;
		return c;
	}
	
	public void complierJavaFile(File f) throws IOException{
		JavaCompiler jc = ToolProvider.getSystemJavaCompiler() ;
		StandardJavaFileManager fileMag = jc.getStandardFileManager(null, null, null) ;//使用默认
		Iterable<? extends JavaFileObject> it = fileMag.getJavaFileObjects(f) ;
		CompilationTask ct = jc.getTask(null, fileMag, null, null, null, it) ;
		ct.call();
		fileMag.close() ;
	}

	private static String packageName2Path(String packageName){
		return StringUtils.trimToEmpty(packageName).replace('.', '/');
	}
	
	public static void main(String[] args) throws Exception {
		DynamicLoad dl = new DynamicLoad();
		File f = dl.storeJavaFile("Test", FileUtils.readFileToByteArray(new File("d:/Test.java")), true);
				//, "public class Test{ public static void main(String[] args) {System.err.println(\"fff\");} }".getBytes()
				//, new File("d:/Test.java")

		System.err.println(f.getAbsolutePath());
		
		dl.complierJavaFile(f);
		
		Class<?> c = dl.loadJavaClass("Test");
		Method m = c.getMethod("main", new Class[]{String[].class});
		m.invoke(c, new Object[]{new String[0]});
		//Class<?> c = dl.loadJavaClass("", "Test");*/
	}
}
